﻿using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Threading.Tasks;
using System.Windows.Data;
using CommunityToolkit.Mvvm.Messaging;
using Downloader;
using FileTransfer.Client;
using FileTransferDesktop.Extensions;
using FileTransferDesktop.Message;
using FileTransferDesktop.Models;
using FileTransferDesktop.Services;
using FileTransferDesktop.ViewModels.Controls;
using FileTransferDesktop.Views.Dialogs;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.VisualBasic;
using Wpf.Ui.Violeta.Controls;
using DownloadDialogViewModel = FileTransferDesktop.ViewModels.Dialogs.DownloadDialogViewModel;
using FileSelectionDialogViewModel = FileTransferDesktop.ViewModels.Dialogs.FileSelectionDialogViewModel;

namespace FileTransferDesktop.ViewModels.Pages;

public partial class DownloadTask : ObservableObject
{
    [ObservableProperty]
    private string _savePath = string.Empty;

    [ObservableProperty]
    private string _taskName = "";

    [ObservableProperty]
    private string _size = "";

    [ObservableProperty]
    private string _progress = "";

    [ObservableProperty]
    private string _message = string.Empty;

    [ObservableProperty]
    private DateTime _downloadTime = DateAndTime.Now;

    [ObservableProperty]
    private string _statusText = "";

    [ObservableProperty]
    private bool _isSelected;

    /// <summary>
    /// 检查文件是否存在
    /// </summary>
    public bool FileExists => !string.IsNullOrEmpty(SavePath) && File.Exists(SavePath);

    /// <summary>
    /// 检查是否是已完成的下载
    /// </summary>
    public bool IsCompleted => StatusText is "已下载" or "下载完成";

    /// <summary>
    /// 检查是否可以打开文件（已完成且文件存在）
    /// </summary>
    public bool CanOpenFile => IsCompleted && FileExists;

    // 当StatusText或SavePath变化时，通知CanOpenFile属性也变化
    partial void OnStatusTextChanged(string value)
    {
        OnPropertyChanged(nameof(CanOpenFile));
        OnPropertyChanged(nameof(IsCompleted));
        OnPropertyChanged(nameof(FileExists));
    }

    partial void OnSavePathChanged(string value)
    {
        OnPropertyChanged(nameof(CanOpenFile));
        OnPropertyChanged(nameof(FileExists));
    }
}

public partial class DownloadViewModel : ObservableObject
{
    [ObservableProperty]
    private ObservableCollection<DownloadTask> _downloadTasks = [];

    [ObservableProperty]
    private int _selectedTabIndex;

    [ObservableProperty]
    private bool? _allSelected = false;
    public SpeedChartViewModel SpeedChartVm { get; } = new();
    private bool _isUpdatingByCode = false;
    private readonly ApiClient _api;

    private readonly IAppSettingsService _settingsService;

    public CollectionView<DownloadTask> DownloadTasksView { get; init; }

    public DownloadViewModel(IAppSettingsService settingsService, IServiceProvider serviceProvider)
    {
        _api = serviceProvider.CreateApiClient();
        _settingsService = settingsService;
        DownloadTasks.CollectionChanged += (_, e) =>
        {
            if (e.NewItems != null)
            {
                foreach (DownloadTask task in e.NewItems)
                {
                    task.PropertyChanged += DownloadTaskPropertyChanged;
                }
            }

            if (e.OldItems != null)
            {
                foreach (DownloadTask task in e.OldItems)
                {
                    task.PropertyChanged -= DownloadTaskPropertyChanged;
                }
            }

            UpdateAllSelectedState();
            return;

            void DownloadTaskPropertyChanged(object? sender, PropertyChangedEventArgs e)
            {
                if (e.PropertyName == nameof(DownloadTask.IsSelected))
                {
                    UpdateAllSelectedState();
                }
            }
        };
        DownloadTasksView = CollectionViewSource.GetDefaultView(DownloadTasks).Cast<DownloadTask>();
        DownloadTasksView.Filter = FilterDownloadTasks;
        DownloadTasksView.SortDescriptions.Add(
            new SortDescription(nameof(DownloadTask.DownloadTime), ListSortDirection.Descending)
        );

        var records = LocalDbService.GetAllDownloads().OrderByDescending(r => r.DownloadTime);
        foreach (var record in records)
        {
            DownloadTasks.Insert(
                0,
                new DownloadTask
                {
                    TaskName = record.FileName,
                    Size = $"{record.FileSize}",
                    Progress = "---",
                    DownloadTime = record.DownloadTime,
                    StatusText = record.Status,
                    Message = "下载完成",
                    IsSelected = false,
                    SavePath = record.FilePath, // 从数据库加载文件路径
                }
            );
        }

        UpdateAllSelectedState();
    }

    partial void OnAllSelectedChanged(bool? oldValue, bool? newValue)
    {
        if (_isUpdatingByCode)
            return;
        var viewList = DownloadTasksView.ToArray();
        if (!oldValue.HasValue)
        {
            AllSelected = true;
            return;
        }
        switch (newValue)
        {
            case false:
            {
                foreach (var task in viewList)
                    task.IsSelected = false;
                break;
            }
            case true:
            {
                foreach (var task in viewList)
                    task.IsSelected = true;
                break;
            }
        }
    }

    private void UpdateAllSelectedState()
    {
        _isUpdatingByCode = true;

        try
        {
            var viewList = DownloadTasksView.ToArray();

            if (viewList.Length == 0)
            {
                AllSelected = false;
                return;
            }

            var selectedCount = viewList.Count(t => t.IsSelected);

            if (selectedCount == viewList.Length)
            {
                AllSelected = true;
            }
            else if (selectedCount == 0)
            {
                AllSelected = false;
            }
            else
            {
                AllSelected = null;
            }
        }
        finally
        {
            _isUpdatingByCode = false;
        }
    }

    partial void OnSelectedTabIndexChanged(int value)
    {
        DownloadTasksView.Refresh();
        UpdateAllSelectedState();
    }

    private bool FilterDownloadTasks(object obj)
    {
        if (obj is not DownloadTask task)
            return false;

        // Tab筛选
        switch (SelectedTabIndex)
        {
            case 1:
                if (task.StatusText != "已下载")
                    return false;
                break;
            case 2:
                if (task.StatusText != "失败")
                    return false;
                break;
        }

        return true;
    }

    [RelayCommand]
    private void ClearAll()
    {
        var toRemove = DownloadTasksView.Where(t => t.IsSelected).ToArray();

        foreach (var task in toRemove)
        {
            var id = LocalDbService.GetDownloadIdByTime(task.DownloadTime);
            if (id != null)
            {
                LocalDbService.DeleteDownload(id);
            }
        }

        WeakReferenceMessenger.Default.Send(new RecycleBinChangedMessage());

        foreach (var task in toRemove)
        {
            DownloadTasks.Remove(task);
        }

        DownloadTasksView.Refresh();
        UpdateAllSelectedState();
    }

    [RelayCommand]
    private async Task OpenDialog()
    {
        var dialogVm = new DownloadDialogViewModel();
        var dialog = new DownloadDialog(dialogVm);
        dialogVm.OnConfirmCode = async void (code) =>
        {
            try
            {
                await HandleDownloadByCodeAsync(code);
            }
            catch (Exception e)
            {
                Debug.WriteLine(e);
            }
        };
        dialogVm.RequestClose += (_, _) => dialog.Hide();
        var showTask = dialog.ShowAsync();
        await Task.Delay(500);
        dialog.Focus();
        await showTask;
    }

    private async Task HandleDownloadByCodeAsync(string code)
    {
        if (string.IsNullOrWhiteSpace(code))
            return;

        try
        {
            var result = await ShareCollection.GetInfoByShareCodeAsync(_api, code);
            if (result.Links.Count == 0)
            {
                var errorDialog = new Wpf.Ui.Controls.MessageBox
                {
                    Title = "错误",
                    Content = "无可用下载链接",
                };
                await errorDialog.ShowDialogAsync();
                return;
            }

            // 多个文件时显示选择弹窗
            var selectionVm = new FileSelectionDialogViewModel();
            var selectionDialog = new FileSelectionDialog(selectionVm);

            selectionVm.SetShareInfo(result.Share);
            selectionVm.OnConfirmSelection = async void (selectedFiles) =>
            {
                try
                {
                    selectionDialog.Hide();
                    foreach (var file in selectedFiles)
                    {
                        await StartDownloadAsync(file, code);
                    }
                }
                catch (Exception e)
                {
                    Debug.WriteLine(e); // TODO 处理异常
                }
            };
            selectionVm.RequestClose += (_, _) => selectionDialog.Hide();

            await selectionDialog.ShowAsync();
        }
        catch (Exception ex)
        {
            Debug.WriteLine($"失败+{ex.Message}");
            await new ContentDialog
            {
                Content = new TextBox { IsReadOnly = true, Text = $"获取失败\n{ex.Message}" },
                CloseButtonText = "关闭",
            }.ShowAsync();
        }
    }

    private async Task StartDownloadAsync(FileTransfer.Client.Http.Model.File file, string code)
    {
        try
        {
            var url = ShareCollection.GetDownloadLink(_api, code, file).ToString();
            var fileName = file.FileName;
            var size = file.FileSize;
            // result.Share.Messages
            Debug.WriteLine($"下载链接: {url},{fileName}"); // Step 1: 确定保存路径
            var downloadPath = (await _settingsService.GetSettingsAsync()).DownloadPath;
            var savePath = Path.Combine(downloadPath, fileName);

            // Step 2: 创建配置
            var config = new DownloadConfiguration
            {
                ChunkCount = 8,
                ParallelDownload = true,
                ReserveStorageSpaceBeforeStartingDownload = true,
            };

            var downloader = new DownloadService(config);

            DownloadTask? currentTask = null;
            downloader.DownloadStarted += (s, e) =>
            {
                Application.Current.Dispatcher.Invoke(() =>
                {
                    SpeedChartVm.SetTransferLabel("正在下载...");
                    SpeedChartVm.SetProgressPercentage(0);

                    currentTask = new DownloadTask
                    {
                        TaskName = fileName,
                        Size = size.ToString(),
                        Message = "正在下载",
                        DownloadTime = DateTime.Now,
                        StatusText = "下载中",
                        IsSelected = false,
                    };
                    DownloadTasks.Add(currentTask);
                });
            };

            var lastUpdate = DateTime.Now;
            downloader.DownloadProgressChanged += (s, e) =>
            {
                // 每500毫秒更新一次进度
                if ((DateTime.Now - lastUpdate).TotalMilliseconds < 500)
                    return;
                lastUpdate = DateTime.Now;
                Application.Current.Dispatcher.Invoke(() =>
                {
                    var written = e.ReceivedBytesSize;
                    var total = e.TotalBytesToReceive;
                    var percent = (double)written / total * 100;

                    SpeedChartVm.UpdateProgress(written);
                    SpeedChartVm.UpdateTransferProgress(written, total);
                    SpeedChartVm.SetProgressPercentage((int)percent);

                    if (currentTask is not null)
                        currentTask.Progress = $"{percent:F1}%";
                });
            };

            downloader.DownloadFileCompleted += (s, e) =>
            {
                Application.Current.Dispatcher.Invoke(() =>
                {
                    if (e.Cancelled || e.Error != null)
                    {
                        SpeedChartVm.SetTransferLabel("下载失败");
                        if (currentTask is not null)
                            currentTask.StatusText = "失败";
                    }
                    else
                    {
                        SpeedChartVm.StartDecay(0);
                        SpeedChartVm.SetTransferLabel("下载完成");
                        SpeedChartVm.SetProgressPercentage(100);

                        SpeedChartVm.UpdateProgress(size);
                        SpeedChartVm.UpdateTransferProgress(size, size);
                        if (currentTask is not null)
                            currentTask.Progress = "100%";
                        if (currentTask is null)
                            return;
                        currentTask.StatusText = "下载完成";
                        currentTask.Message = "下载成功";
                        currentTask.SavePath = savePath; // 保存文件路径
                        LocalDbService.SaveDownload(
                            new DownloadRecord
                            {
                                FileName = fileName,
                                DownloadTime = DateTime.Now,
                                FileSize = currentTask.Size,
                                Status = "已下载",
                                SourceUrl = url,
                                Message = "下载成功",
                                FilePath = savePath, // 保存文件路径到数据库
                            }
                        );
                    }
                });
            }; // Step 4: 下载文件
            await downloader.DownloadFileTaskAsync(url, savePath);
        }
        catch (Exception ex)
        {
            Debug.WriteLine($"失败+{ex.Message}");
        }
    }

    [RelayCommand]
    private static void OpenFile(DownloadTask? task)
    {
        if (task is not { CanOpenFile: true })
            return;

        try
        {
            // 使用Windows资源管理器打开并选中文件
            Process.Start("explorer.exe", $"/select,\"{task.SavePath}\"");
        }
        catch (Exception ex)
        {
            Debug.WriteLine($"打开文件失败: {ex.Message}");

            // 如果无法选中文件，尝试打开文件所在目录
            try
            {
                var directory = Path.GetDirectoryName(task.SavePath);
                if (!string.IsNullOrEmpty(directory) && Directory.Exists(directory))
                {
                    Process.Start("explorer.exe", directory);
                }
            }
            catch (Exception ex2)
            {
                Debug.WriteLine($"打开目录失败: {ex2.Message}");
            }
        }
    }
}
